Fork me on GitHub

webpack Hot Module Replacement

Webpack with React


简单说webpack是一个module加载器,可以把项目内html,js,css以模块化的方式加载进项目内。
提供了很多的loader用于加载、解析不同的lib 或者 frame。
提供了许多plugin,实现诸如全局变量、模块热替换等功能。

总之是相当的全面,可以实现大部分前端工程化、模块化的功能

Hot Module Replacement


HMR意思是模块热替换(字面翻译哈哈),就是你在代码中修改代码,无需在浏览器中刷新,能够自己的更新浏览器中的代码,直接呈现在你的面前,解放你的双手,节省你的键盘。

实现方式

首先你要自己build一个项目,配置好你webpack.config,然后写一个简单的module。
你会在这之中看到Hot Module Replacement 的相关实现方式,大家也可以试试。
这里主要讲的是另外的实现方式哈。

server.js

/*
    path NodeJs Api 用于操作目录对象
    webpack
    dev-server 其实搭建了一个小型的express项目
    config 是你的webpack配置文件
*/
var path = require('path');
var webpack = require('webpack');
var express = require('express');
var config = require("./webpack.dev.config");

/*
    app 获取一个express的实例
    compile 返回一个Compiler实例
    webpack-dev-middleware            
    webpack hot middleware
    用来实现热替换的中间件
    app.get('*'…… 配置路由        
    最后启用端口监听        
*/
var app = express();
var compile = webpack(config);

app.use(require('webpack-dev-middleware')(compile,{
    noInfo: true,
    publicPath: config.output.publicPath
}));

app.use(require('webpack-hot-middleware')(compile,{
    log: console.log, path: '/__webpack_hmr', heartbeat: 10 * 1000
}));

app.get('*',function(req, res){
    res.sendFile(path.join(__dirname,'index.html'));
});

app.listen(8000,'127.0.0.1',function(){});

webpack.dev.config.js

var webpack = require("webpack");
var path = require("path");
var config = {
    devtool: 'source-map',
    //  app 获取一个express的实例
    //  compile 返回一个Compiler实例
    //  webpack-dev-middleware            
    //  webpack hot middleware
    //  用来实现热替换的中间件
    //  app.get('*'…… 配置路由        
    //  最后启用端口监听        
    entry:[
        'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&reload=true',
        __dirname + '/src/entry.js'
    ],
    /*
         这里需要注意一下,
         运行node server.js时不会生成文件到dist中,需要运行build进行构建才会生成
         其次,配置的filename在你的项目中找不到的,
         要想使用entry.js,在html中引用地址写成'/static/entry.js'是可以引用到的
    */
    output: {
        path:path.resolve(__dirname,'dist'),
        filename: "entry.js",
        publicPath:"/static/"
    },
    /*
        new webpack.optimize.OccurenceOrderPlugin(),
        为组件分配ID,通过这个插件webpack可以分析和优先考虑使用最多的模块,并为它们分配最小的ID
        new webpack.HotModuleReplacementPlugin()
        这个就是实现HMR的plugin
        new webpack.NoErrorsPlugin()
        发现错误不打断程序
    */
    plugins: [
        new webpack.optimize.OccurenceOrderPlugin(),
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoErrorsPlugin()
    ],
    module:{
        loaders:[
            /*
               babel加载器
               exclude除去的意思
               query的preset,进行es2015,react加载?
               test: A condition that must be met
               exclude: A condition that must not be met
               include: An array of paths or files where the imported files will be transformed by the loader
               loader: A string of “!” separated loaders
               loaders: An array of loaders as string
             */
            {
                test:/\.js$/,
                exclude:/(node_modules)/,
                loader:'babel-loader',
                include: path.join(__dirname, 'src'),
                query:{
                    presets:['es2015','react']
                }
            }
        ]
    }
}
module.exports = config;

OK,现在执行,可以看到页面出现在大家面前,修改自己的module文件发现页面刷新了,貌似这个跟咱们预想的不太一样耶

一顿寻找中…

发现了react-transform

在root下建立一个.babelrc

.babelrc

首先安装

npm install react-transform --save && npm install react-transform-hmr --save

然后配置.babelrc

{
  "presets": ["react", "es2015"],
  "env": {
    "development": {
      "plugins": [
        ["react-transform", {
          "transforms": [{
            "transform": "react-transform-hmr",
            "imports": ["react"],
            "locals": ["module"]
          }]
        }]
      ]
    },
    "production": {
      "plugins": []
    }
  }
}

Perfect !!!
@GitHub webpack-dev-middleware
@手把手深入理解 webpack dev middleware 原理與相關 plugins
@babel-plugin-react-transform